<!-- 员工管理模块 -->
<template>
  <div class="dashboard-container">
    <div class="app-container">
      <!-- 顶部工具栏 使用公用组件 -->
      <PageTools :show-before="showBefore">
        <template #before>
          <span>共{{ page.total }}条记录</span>
        </template>
        <template #after>
          <el-button
            size="small"
            type="warning"
            @click="$router.push('/import?type=user')"
            >excel导入</el-button
          >
          <el-button size="small" type="danger" @click="exportDataHandler"
            >excel导出</el-button
          >
          <el-button size="small" type="primary" @click="showDialog = true"
            >新增员工</el-button
          >
        </template>
      </PageTools>
      <!-- 中间主体内容 -->
      <el-card>
        <!-- 表格 -->
        <el-table border :data="list">
          <!-- sortable 表示可排序 -->
          <el-table-column
            label="序号"
            type="index"
            sortable=""
            align="center"
          />
          <el-table-column
            label="姓名"
            prop="username"
            sortable=""
            align="center"
          />
          <el-table-column label="头像" align="center">
            <template slot-scope="{ row }">
              <img
                :src="row.staffPhoto ? row.staffPhoto : defaultImg"
                alt=""
                class="avator"
                @click="qrCodeHandler(row.staffPhoto)"
              />
            </template>
          </el-table-column>
          <el-table-column
            label="工号"
            prop="workNumber"
            sortable=""
            align="center"
          />
          <el-table-column
            label="手机号"
            prop="mobile"
            sortable=""
            align="center"
          />
          <!-- 绑定formatter属性来格式化聘用形式，formatEmployment是一个回调函数 -->
          <el-table-column
            label="聘用形式"
            prop="formOfEmployment"
            sortable=""
            :formatter="formatEmployment"
            align="center"
          />
          <el-table-column
            label="部门"
            prop="departmentName"
            align="center"
            sortable=""
          />
          <el-table-column label="入职时间" align="center" sortable="">
            <!-- 使用全局过滤器，格式化时间  formatDate 这个函数在 views/filters文件夹中-->
            <template slot-scope="{ row }">
              {{ row.timeOfEntry | formatDate }}
            </template>
          </el-table-column>
          <el-table-column
            label="账户状态"
            prop="enableState"
            align="center"
            sortable=""
          >
            <template slot-scope="{ row }">
              <!-- 根据当前状态来确定 是否打开开关，等于1就打开，绑定v-model或者value都可以 -->
              <el-switch :value="row.enableState === 1"></el-switch>
            </template>
          </el-table-column>
          <el-table-column
            label="操作"
            sortable=""
            align="center"
            fixed="right"
            width="280"
          >
            <template slot-scope="{ row }">
              <!-- 查看的时候携带id跳转到员工详情页 -->
              <el-button
                type="text"
                size="small"
                @click="$router.push(`/employees/detail/${row.id}`)"
                >查看</el-button
              >
              <el-button type="text" size="small">转正</el-button>
              <el-button type="text" size="small">调岗</el-button>
              <el-button type="text" size="small">离职</el-button>
              <el-button
                type="text"
                size="small"
                @click="assignRoleHandler(row.id)"
                >角色</el-button
              >
              <el-button
                type="text"
                size="small"
                @click="deleteEmployee(row.id)"
                >删除</el-button
              >
            </template>
          </el-table-column>
        </el-table>
        <!-- 分页 -->
        <el-row
          type="flex"
          justify="center"
          align="middle"
          style="height: 60px"
        >
          <el-pagination
            :current-page="page.page"
            :page-size="page.size"
            :total="page.total"
            :page-sizes="[2, 3, 5, 10]"
            layout="total, sizes, prev, pager, next, jumper"
            @size-change="handleSizeChange"
            @current-change="changePage"
          ></el-pagination>
        </el-row>
      </el-card>
      <!-- 添加员工弹窗组件 -->
      <AddEmployee
        :show-dialog.sync="showDialog"
        @updateEmployeeList="getEmployeeList"
      ></AddEmployee>

      <!-- 二维码弹窗组件 -->
      <el-dialog
        title="二维码"
        :visible.sync="showCodeDialog"
        @close="imgUrl = ''"
      >
        <el-row type="flex" justify="center">
          <canvas ref="myCanvas" />
        </el-row>
      </el-dialog>

      <!-- 分配角色弹窗组件 -->
      <AssignRole
        ref="assignRole"
        :show-role-dialog.sync="showRoleDialog"
        :user-id="userId"
      ></AssignRole>
    </div>
  </div>
</template>

<script>
import { getEmployeeListAPI, delEmployeeListAPI } from '@/api/employees'
import EmployeeEnum from '@/api/constant/employees' // 导入员工的枚举对象
import AddEmployee from './components/AddEmployee.vue' // 新增员工弹窗组件
import { formatDate } from '@/filters' // 格式化日期时间
import defaultImg from '@/assets/common/img.jpeg' // 默认头像
import QrCode from 'qrcode' // 二维码组件
import AssignRole from './components/AssignRole.vue' // 导入分配角色组件
export default {
  components: { AddEmployee, AssignRole },
  data() {
    return {
      showBefore: true,
      list: [], // 接数据的
      page: {
        page: 1, // 当前页码
        size: 10, // 每页条数
        total: 0 // 总数
      },
      showDialog: false, // 控制新增员工弹窗的显示和隐藏
      defaultImg: defaultImg, // 接收一下 defaultImg
      showCodeDialog: false, // 控制头像二维码的显示和隐藏
      showRoleDialog: false, // 控制分配角色弹窗的显示和隐藏
      userId: '' // 角色id
    }
  },
  created() {
    this.getEmployeeList() // 获取员工列表
  },
  methods: {
    // 获取员工列表
    async getEmployeeList() {
      const res = await getEmployeeListAPI(this.page)
      // console.log('员工列表', res)
      if (!res.success) return false
      this.page.total = res.data.total
      this.list = res.data.rows
    },
    // 删除员工
    async deleteEmployee(id) {
      // 询问用户是否删除
      const confirmResult = await this.$confirm('是否确认删除？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).catch((err) => err)
      // 取消了删除
      if (confirmResult === 'cancel') return this.$message.warning('取消了删除')
      const res = await delEmployeeListAPI(id)
      if (!res.success) return this.$message.error(res.message)
      this.$message.success(res.message)
      // 解决最后一页只有一条数据，删除之后页码不更新
      if (this.list.length === 1 && this.page.page > 1) {
        // this.list 表示当前页码的列表，当前页展示多少条数据，list就是多少条数据
        // this.list.length === 1,虽然你调接口删除数据，但是那是后端删除，前端数组你没有用代码去修改她
        // this.page.page>1，保证page的最小值为 1
        this.page.page--
      }
      this.getEmployeeList() // 获取员工列表
    },
    // 页码改变时的回调
    changePage(newPage) {
      this.page.page = newPage
      this.getEmployeeList()
    },
    // 每一页条数变化时的回调
    handleSizeChange(val) {
      this.page.size = val
      this.getEmployeeList()
    },
    // 格式化聘用形式
    formatEmployment(row, column, cellValue, index) {
      // cellValue 就是当前单元格的值，就是去找cellValue对应的值，1是正式 2是非正式
      const obj = EmployeeEnum.hireType.find((item) => item.id === cellValue)
      return obj ? obj.value : '未知'
    },
    // excel导出
    exportDataHandler() {
      // 声明对应关系
      const headers = {
        姓名: 'username',
        手机号: 'mobile',
        入职日期: 'timeOfEntry',
        聘用形式: 'formOfEmployment',
        转正日期: 'correctionTime',
        工号: 'workNumber',
        部门: 'departmentName'
      }
      // 注意：1.数据格式需要转化 [{username:'张三',mobile:188xxx}] => [[]]
      //      2.要转化的数据格式还要和表头的顺序对上，而且转出的标题还是中文
      import('@/vendor/Export2Excel').then(async (excel) => {
        // excel 是引入文件的导出对象
        // 现在没有接口获取所有的员工数据 => 思路：接口还是原来的接口，就是第一页展示所有的数据。将page(当前页码)设置为1，size(每页条数)设置为数据总数(this.page.total)
        // res -> 获取到所有员工数据
        const res = await getEmployeeListAPI({
          page: 1,
          size: this.page.total
        })
        // 将对应关系header和获取到的员工数据传给这个方法，这个方法返回的data就是我们需要的数据结 =>[[]]
        const data = this.formatJson(headers, res.data.rows)

        // multiHeader 字段个数要和真正的列数相等，想要跨列，多余的需要使用空字符串
        const multiHeader = [['姓名', '主要信息', '', '', '', '', '部门']]
        const merges = ['A1:A2', 'B1:F1', 'G1:G2']
        excel.export_json_to_excel({
          header: Object.keys(headers), //  Object.keys(headers) 得到一个个中文的数组,就是我们需要的表头结构
          data: data,
          filename: '员工资料表', // 导出文件名,非必填
          multiHeader: multiHeader, // 复杂表头的部分，默认值 => [[]]
          merges: merges // 需要合并的部分，默认值 => []
        })

        // excel.export_json_to_excel({
        //   header: ['姓名', '工资'], // 表头 必填
        //   data: [['张三', 3000]], // 具体数据 必填
        //   filename: '员工列表' // 导出文件名,非必填
        //   // autoWidth: true // 单元格是否要自适应宽度，非必填，默认true
        //   // bookType: 'xlsx' // 导出文件类型，非必填，默认xlsx
        // })
      })
    },
    // 该方法用来处理数据，将数组转为二维数组 [{ username: '张三'，mobile: 188xxx},{},{}]  => [['张三',188xxx],[],[]]
    formatJson(headers, rows) {
      return rows.map((item) => {
        // item就是每一项 => {id:xx,username:xxx,...}
        return Object.keys(headers).map((key) => {
          // 此时的key是中文的
          // headers[key] => 拿到英文的key
          // item[headers[key]] => 拿到值 ['张三','188xxx'...]
          if (
            headers[key] === 'timeOfEntry' ||
            headers[key] === 'correctionTime'
          ) {
            // 这里需要格式化时间,formatDate 这个方法是在views/filters中
            return formatDate(item[headers[key]])
          } else if (headers[key] === 'formOfEmployment') {
            // 处理聘用形式 1->正式  2->非正式
            const obj = EmployeeEnum.hireType.find(
              (obj) => obj.id === item[headers[key]]
            )
            return obj ? obj.value : '未知'
          }
          return item[headers[key]]
        })
      })
    },
    // 点击头像生成二维码
    qrCodeHandler(url) {
      if (url) {
        // 头像存在在显示弹窗
        this.showCodeDialog = true
        this.$nextTick(() => {
          // 放在nextTick中就是确定此时有dom对象了，可以获取到ref
          // 转化二维码后面的信息可以是任意字符串，如果是一个地址的话，就会跳到该地址，如果不是地址就显示该字符串内容
          QrCode.toCanvas(this.$refs.myCanvas, url) // 将地址转化成二维码
        })
      } else {
        this.$message.warning('该用户没有上传头像')
      }
    },
    // 分配角色
    async assignRoleHandler(id) {
      this.userId = id
      // 通过给子组件绑定ref属性，来获取子组件的方法
      await this.$refs.assignRole.getUserDetailsById(id) // 调用子组件方法 异步方法,前面加await防止页面闪烁
      this.showRoleDialog = true
    }
  }
}
</script>

<style lang="scss" scoped>
.avator {
  height: 80px;
  width: 80px;
  line-height: 80px;
  border-radius: 50%;
}
</style>
